package com.hzhh123.crypto.utils;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;

import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.HashMap;
import java.util.Map;

import org.bouncycastle.util.encoders.Hex;

/**
 * @author hzhh123
 * @version 1.0
 * @date 2022/4/13 11:33
 * @des
 */
public class Sm2Utils {
    /**
     * 类型
     */
    public static final String ENCRYPT_TYPE = "SM2";

    /**
     * 获取公钥的key
     */
    public static final String PUBLIC_KEY = "SM2PublicKey";

    /**
     * 获取私钥的key
     */
    public static final String PRIVATE_KEY = "SM2PrivateKey";

    public static final String ENCRYPT_MODE_BCD="BCD";
    public static final String ENCRYPT_MODE_HEX="HEX";
    public static final String ENCRYPT_MODE_BASE64="BASE64";
    /**
     * 获取公私钥-请获取一次后保存公私钥使用
     *
     * @return
     */
    public static Map<String, String> generateKeyPairBase64() {
        try {
            KeyPair pair = SecureUtil.generateKeyPair(ENCRYPT_TYPE);
            PrivateKey privateKey = pair.getPrivate();
            PublicKey publicKey = pair.getPublic();
            // 获取 公钥和私钥 的 编码格式（通过该 编码格式 可以反过来 生成公钥和私钥对象）
            byte[] pubEncBytes = publicKey.getEncoded();
            byte[] priEncBytes = privateKey.getEncoded();

            // 把 公钥和私钥 的 编码格式 转换为 Base64文本 方便保存
            String pubEncBase64 = Base64.encode(pubEncBytes);
            String priEncBase64 = Base64.encode(priEncBytes);

            Map<String, String> map = new HashMap<String, String>(2);
            map.put(PUBLIC_KEY, pubEncBase64);
            map.put(PRIVATE_KEY, priEncBase64);

            return map;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Map<String, String> generateKeyPairHex() {
      try {
          KeyPair pair = SecureUtil.generateKeyPair(ENCRYPT_TYPE);
          PrivateKey privateKey = pair.getPrivate();
          PublicKey publicKey = pair.getPublic();
          // 获取 公钥和私钥 的 编码格式（通过该 编码格式 可以反过来 生成公钥和私钥对象）
          byte[] pubEncBytes = publicKey.getEncoded();
          byte[] priEncBytes = privateKey.getEncoded();

          // 把 公钥和私钥 的 编码格式 转换为 Hash文本 方便保存
          String pubEncHex = Hex.toHexString(pubEncBytes);
          String priEncHex =Hex.toHexString(priEncBytes);

          Map<String, String> map = new HashMap<String, String>(2);
          map.put(PUBLIC_KEY, pubEncHex);
          map.put(PRIVATE_KEY, priEncHex);

          return map;
      } catch (Exception e) {
          e.printStackTrace();
      }
      return null;
  }

    public static String encrypt(String str,String pubKey,String mode){
        byte[] keyBytes = Validator.isHex(pubKey) ? HexUtil.decodeHex(pubKey) : Base64.decode(pubKey);
        SM2 sm2 = SmUtil.sm2(null, keyBytes);
        if(mode.equals(ENCRYPT_MODE_BCD)) {
            return sm2.encryptBcd(str, KeyType.PublicKey);
        }
        if(mode.equals(ENCRYPT_MODE_HEX)) {
            return sm2.encryptHex(str, KeyType.PublicKey);
        }
        return sm2.encryptBase64(str,KeyType.PublicKey);
    }

    public static String decrypt(String str,String pribKey,String mode){
        byte[] keyBytes = Validator.isHex(pribKey) ? HexUtil.decodeHex(pribKey) : Base64.decode(pribKey);
        SM2 sm2 = SmUtil.sm2(keyBytes,null );
        if(mode.equals(ENCRYPT_MODE_BCD)) {
            return sm2.decryptStrFromBcd(str, KeyType.PrivateKey);
        }
        return sm2.decryptStr(str, KeyType.PrivateKey);
    }

    public static void main(String[] args) {
        //Map<String, String> stringStringMap = generateKeyPairBase64();
        //System.out.println(stringStringMap.get(PUBLIC_KEY));
        //System.out.println();
        //System.out.println();
        //System.out.println(stringStringMap.get(PRIVATE_KEY));
        String pubKey="MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEilivBGPrnunZqZL9Coa+Ir4p63nPgAS95oYFaKYPd+BKHbouiqRMd/WPgwFnZSdPZ1IRrM3TNlHdO65plFwNDw==";
        String s="{\"username\":\"admin\",\"password\":\"123\"}";
        System.out.println(encrypt(s,pubKey,"BASE64"));
        String priKey = "MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQggz7cN/iSujCLHhGaW8PPHuHiFWHgQJwIVtth/85zQ5GgCgYIKoEcz1UBgi2hRANCAASKWK8EY+ue6dmpkv0Khr4ivinrec+ABL3mhgVopg934Eodui6KpEx39Y+DAWdlJ09nUhGszdM2Ud07rmmUXA0P";
        String str = "1b400e753dc2cfa01d98caeb23b07172509226bbf24749972486bf44cf35d2b476bb627708ccf9b140f527dd570d3a3e7a0cb9f469a917be229d8181956aef9f";
        String decrypt = decrypt(str, priKey, "");
        System.out.println(decrypt);
    }
}
